#include <stdio.h>
#include <string.h>

#include <time.h>
#include <sys/time.h>
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/gpio.h"

#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "timeutils.h"
#include "modmachine.h"
#include "machine_rtc.h"
#include "modesp32.h"
#include "py/mpconfig.h"

#include "weonewire.h"
#include "py/objmodule.h"

// 兼容性：若未由 MicroPython 头文件定义 STATIC，则回退为 static
#ifndef STATIC
#define STATIC static
#endif

uint8_t onewire_reset(uint8_t pinNum)
{
    uint8_t r;
    uint8_t pinMask = pinNum;
    gpio_set_direction(pinMask, GPIO_MODE_OUTPUT);
    // gpio_set_level(pinMask,0);
    mp_hal_pin_write(pinMask, 0);
    mp_hal_delay_us_fast(480);
    uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
    gpio_set_direction(pinMask, GPIO_MODE_INPUT);
    mp_hal_delay_us_fast(50);
    r = gpio_get_level(pinMask);
    MICROPY_END_ATOMIC_SECTION(i);
    mp_hal_delay_us_fast(80);
    return r;
}

STATIC mp_obj_t reset(mp_obj_t pinNum)
{
    uint8_t r;
    uint8_t pinMask = mp_obj_get_int(pinNum);
    gpio_set_direction(pinMask, GPIO_MODE_OUTPUT);
    gpio_set_level(pinMask,0);
    mp_hal_delay_us_fast(480);
    uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
    gpio_set_direction(pinMask, GPIO_MODE_INPUT);
    mp_hal_delay_us_fast(50);
    r = gpio_get_level(pinMask);
    MICROPY_END_ATOMIC_SECTION(i);
    mp_hal_delay_us_fast(80);
    return mp_obj_new_int(r);
}
MP_DEFINE_CONST_FUN_OBJ_1(reset_obj,reset);

STATIC mp_obj_t respond(mp_obj_t pinNum)
{
    uint8_t pinMask = mp_obj_get_int(pinNum);

    unsigned long startTime=0;
    gpio_set_direction(pinMask, GPIO_MODE_INPUT);
    while(gpio_get_level(pinMask) == 1){
        startTime++;
        mp_hal_delay_us_fast(1);
        if(startTime > 50000){
        	return mp_obj_new_int(1);
        }
    }
    while(gpio_get_level(pinMask) == 0);
    gpio_set_direction(pinMask, GPIO_MODE_OUTPUT);
    gpio_set_level(pinMask,0);
    mp_hal_delay_us_fast(30);
    gpio_set_direction(pinMask, GPIO_MODE_INPUT);
    return mp_obj_new_int(0);
}
MP_DEFINE_CONST_FUN_OBJ_1(respond_obj,respond);

STATIC mp_obj_t writebyte(mp_obj_t pinNum, mp_obj_t value_in)
{
    uint16_t get_pin = mp_obj_get_int(pinNum);
    uint8_t pinMask = get_pin&0xff;
    uint8_t time_flag = (get_pin>>8)&0xff;
    uint8_t v = mp_obj_get_int(value_in);
    gpio_set_direction(pinMask, GPIO_MODE_OUTPUT);
    for(uint8_t i=0;i<8;i++){
        uint32_t t = MICROPY_BEGIN_ATOMIC_SECTION();
        gpio_set_level(pinMask,0);
        if(time_flag==1){
            mp_hal_delay_us_fast(15);
        }
        else{
            mp_hal_delay_us_fast(7);
        }

        if (v&0x01){
            gpio_set_level(pinMask,1);
        }else{
            gpio_set_level(pinMask,0);
        }
        v=v>>1;
        mp_hal_delay_us_fast(35);
        gpio_set_level(pinMask,1);
        mp_hal_delay_us_fast(12);
        MICROPY_END_ATOMIC_SECTION(t);
    }
    gpio_set_direction(pinMask, GPIO_MODE_INPUT);
    return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_2(writebyte_obj,writebyte);

STATIC mp_obj_t readbyte(mp_obj_t pinNum)
{
    uint8_t j=0,k=0;
    uint32_t startTime=0;
    uint8_t pinMask = mp_obj_get_int(pinNum);
    for (int i = 0; i < 8; ++i){
        startTime=0;
        gpio_set_direction(pinMask, GPIO_MODE_INPUT);
        uint32_t t = MICROPY_BEGIN_ATOMIC_SECTION();
        while(gpio_get_level(pinMask)==1)
        {
            startTime++;
            mp_hal_delay_us_fast(1);
            if (startTime>1000){
                break;
            }
        }
        mp_hal_delay_us_fast(35);
        j=gpio_get_level(pinMask);
        MICROPY_END_ATOMIC_SECTION(t);
        mp_hal_delay_us_fast(45);
        k = (j<<7)|(k>>1);
    }

    return mp_obj_new_int(k);
}
MP_DEFINE_CONST_FUN_OBJ_1(readbyte_obj,readbyte);

STATIC const mp_rom_map_elem_t mp_module_weonewire_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_weonewire) },
    { MP_ROM_QSTR(MP_QSTR_reset),(mp_obj_t)&reset_obj },
    { MP_ROM_QSTR(MP_QSTR_respond),(mp_obj_t)&respond_obj },
    { MP_ROM_QSTR(MP_QSTR_writebyte),(mp_obj_t)&writebyte_obj },
    { MP_ROM_QSTR(MP_QSTR_readbyte),(mp_obj_t)&readbyte_obj },

};

STATIC MP_DEFINE_CONST_DICT(mp_module_weonewire_globals, mp_module_weonewire_globals_table);

const mp_obj_module_t mp_module_weonewire = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t*)&mp_module_weonewire_globals,
};

// 在 MicroPython 启动时注册模块，使其可通过 `import weonewire` 使用
MP_REGISTER_MODULE(MP_QSTR_weonewire, mp_module_weonewire);
